/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package domino;

import java.awt.*;
import java.util.*;
import javax.swing.*;

/**
 *
 * @author Jules
 */
public class frmDomino extends javax.swing.JFrame implements Observer {

    public static final String PUERTO_POR_DEFECTO = "5101";
    private static final String COMER_TEXTO_BOTON = "Comer";
    private static final String LOCALHOST_TEXT = "localhost";
    private static final String PASAR_TEXTO_BOTON = "Pasar";
    //Si está en true coloca valores por defecto que facilitan las pruebas.
    //En producción debería estar en false.
    private static final boolean USA_VALORES_POR_DEFECTO = true;
    //Si está en true no es necesario presionar el botón conectar.
    //En producción debería estar en false
    private static final boolean CONECTARSE_AL_INICIAR = true;
    HashMap<Integer, JPanel> trenes = new HashMap<Integer, JPanel>();
    HashMap<Integer, PanelDropTarget> drops = new HashMap<Integer, PanelDropTarget>();
    JPanel panelTrenPrincipal = null;
    PanelDropTarget dropPrincipal = null;
    Ficha Motor;
    ConectorJuego conector;
    private boolean turnoEnProceso;
    boolean haComido = false;

    /**
     * Creates new form frmDomino
     */
    public frmDomino() {
        initComponents();
        if (USA_VALORES_POR_DEFECTO) {
            this.txtServidor.setText(LOCALHOST_TEXT);
            this.txtPuerto.setText(PUERTO_POR_DEFECTO);
        }
        tablero.setLayout(new BoxLayout(tablero, BoxLayout.Y_AXIS));
        if (CONECTARSE_AL_INICIAR) {
            conectarConServidor();
        } else {
            cmdComer.setEnabled(false);
        }
    }

    private void conectarConServidor() throws NumberFormatException {
        if (conector == null || !conector.isConectado()) {
            int puerto = Integer.parseInt(txtPuerto.getText());
            conector = new ConectorJuego(txtServidor.getText(), puerto);
            conector.registrar(this);
            conector.Conectar();
            if (conector.isConectado()) {
                //terminarTurno();
            }
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        txtServidor = new javax.swing.JTextField();
        lblServidor = new javax.swing.JLabel();
        lblPuerto = new javax.swing.JLabel();
        txtPuerto = new javax.swing.JTextField();
        cmdConectar = new javax.swing.JButton();
        panelFichas = new javax.swing.JPanel();
        tablero = new javax.swing.JPanel();
        cmdComer = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtConsola = new javax.swing.JTextArea();
        cmdComenzar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        lblServidor.setText("Servidor");

        lblPuerto.setText("Puerto");

        cmdConectar.setText("Conectar");
        cmdConectar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdConectarActionPerformed(evt);
            }
        });

        panelFichas.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        panelFichas.setName("panelFichas"); // NOI18N

        tablero.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        tablero.setName("tablero"); // NOI18N
        tablero.setLayout(new javax.swing.BoxLayout(tablero, javax.swing.BoxLayout.LINE_AXIS));

        cmdComer.setText("Comer");
        cmdComer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdComerActionPerformed(evt);
            }
        });

        txtConsola.setColumns(20);
        txtConsola.setEditable(false);
        txtConsola.setRows(5);
        jScrollPane1.setViewportView(txtConsola);

        cmdComenzar.setText("Comenzar");
        cmdComenzar.setToolTipText("");
        cmdComenzar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdComenzarActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(tablero, javax.swing.GroupLayout.DEFAULT_SIZE, 877, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addGap(22, 22, 22)
                        .addComponent(lblServidor)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(txtServidor, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(lblPuerto)
                        .addGap(18, 18, 18)
                        .addComponent(txtPuerto, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(cmdConectar)
                        .addGap(26, 26, 26))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 794, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(cmdComer))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(panelFichas, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap(26, Short.MAX_VALUE))
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(layout.createSequentialGroup()
                            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(cmdComenzar))
                        .addGroup(layout.createSequentialGroup()
                            .addGap(12, 12, 12)
                            .addComponent(tablero, javax.swing.GroupLayout.DEFAULT_SIZE, 877, Short.MAX_VALUE)))
                    .addContainerGap(26, Short.MAX_VALUE)))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(28, 28, 28)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblServidor)
                    .addComponent(txtServidor, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblPuerto)
                    .addComponent(txtPuerto, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(cmdConectar)
                    .addComponent(cmdComenzar))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(tablero, javax.swing.GroupLayout.PREFERRED_SIZE, 297, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(panelFichas, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(cmdComer)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 128, Short.MAX_VALUE))
                .addContainerGap())
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(72, 72, 72)
                    .addComponent(tablero, javax.swing.GroupLayout.PREFERRED_SIZE, 297, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(211, Short.MAX_VALUE)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void cmdConectarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdConectarActionPerformed
        conectarConServidor();
    }//GEN-LAST:event_cmdConectarActionPerformed

    /**
     * Se ejecuta al momento de presionar el botón comer.
     * @param evt El objeto que contiene todos los parámetros del evento
     */
    private void cmdComerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdComerActionPerformed
        //Si actualmente el botón dice Comer entonces debe tratar de solicitar
        //una pieza nueva al servidor. Independientemente de si la respuesta es una
        //pieza o un mensaje de que ya no hay más piezas en el pozo se debe cambiar
        //se debe cambiar el mensaje del botón a Pasar
        if (!haComido) {
            conector.Comer();
            haComido = true;
            cmdComer.setText(PASAR_TEXTO_BOTON);
        } //Si el botón ya dice pasar simplemente notificamos al server 
        else {
            conector.pasar();            
            terminarTurno();
        }
    }//GEN-LAST:event_cmdComerActionPerformed

    private void cmdComenzarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdComenzarActionPerformed
        // TODO add your handling code here:
        conector.comenzar();
    }//GEN-LAST:event_cmdComenzarActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(frmDomino.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(frmDomino.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(frmDomino.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(frmDomino.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new frmDomino().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cmdComenzar;
    private javax.swing.JButton cmdComer;
    private javax.swing.JButton cmdConectar;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel lblPuerto;
    private javax.swing.JLabel lblServidor;
    private javax.swing.JPanel panelFichas;
    private javax.swing.JPanel tablero;
    private javax.swing.JTextArea txtConsola;
    private javax.swing.JTextField txtPuerto;
    private javax.swing.JTextField txtServidor;
    // End of variables declaration//GEN-END:variables

    @Override
    public void Actualizar(String mensaje) {

        StringBuilder sb = new StringBuilder();

        sb.append(mensaje);
        sb.append('\n');
        sb.append(txtConsola.getText());

        txtConsola.setText(sb.toString());
    }

    @Override
    public void ActualizarFichas(Iterable<Ficha> fichas) {

        panelFichas.removeAll();
        panelFichas.setLayout(new FlowLayout());

        Iterator<Ficha> it = fichas.iterator();
        while (it.hasNext()) {
            Ficha ficha = it.next();
            FichaBoton boton = new FichaBoton(ficha);
            boton.setPanel(panelFichas);
            panelFichas.add(boton);
        }
        panelFichas.validate();
        //panelFichas.repaint();
    }

    @Override
    public void comerFicha(Ficha ficha) {
        FichaBoton nueva = new FichaBoton(ficha);
        nueva.setPanel(panelFichas);
        panelFichas.add(nueva);
        panelFichas.validate();
    }

    //FIXME Éste método necesita un buen refactor, está muy desorganizado.
    @Override
    public void mostrarTren(Tren t) {
        boolean trenPrincipal = t.esPrincipal();
        boolean miTablero = conector.getNumero() == t.getNumero();
        JPanel panelTren;
        PanelDropTarget drop;

        if (!trenPrincipal) {
            if (!trenes.containsKey(t.getNumero())) {
                JPanel add = new JPanel();                
                add.setLayout(new FlowLayout());
                drop = new PanelDropTarget(add, this);
                drop.setTren(t);                
                drop.setConector(conector);
                drop.setMotor(Motor);
                trenes.put(t.getNumero(), add);
                drops.put(t.getNumero(), drop);
                tablero.add(add);
                tablero.validate();
            }
            panelTren = trenes.get(t.getNumero());
            drop = drops.get(t.getNumero());
            drop.setHabilitado(t.getMarcado() || miTablero);    
            if (t.getMarcado()) {
                panelTren.setBackground(Color.red);
            }
            else{
                if (miTablero) {
                    panelTren.setBorder(BorderFactory.createLineBorder(new Color(255, 0, 0)));
                    panelTren.setBackground(Color.WHITE);
                } else {
                    panelTren.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
                    panelTren.setBackground(Color.GRAY);
                }            
            }       
        } else {
            if (panelTrenPrincipal == null) {
                setTrenPrincipal();
            }
            panelTren = panelTrenPrincipal;
            dropPrincipal.setTren(t);
            dropPrincipal.setHabilitado(true);
        }

        //Si está marcado entonces le cambiamos el fondo para denotar
        //que cualquiera puede tirar en él


        panelTren.removeAll();
        Iterator<Ficha> i = t.getFichas().iterator();
        while (i.hasNext()) {
            Ficha ficha = i.next();
            FichaBoton boton = new FichaBoton(ficha);
            boton.setUtilizada(true);
            boton.setPanel(panelTren);
            panelTren.add(boton);
        }
        panelTren.validate();
        tablero.validate();
    }

    private void setTrenPrincipal() {
        panelTrenPrincipal = new JPanel();
        panelTrenPrincipal.setLayout(new FlowLayout());

        panelTrenPrincipal.setBorder(BorderFactory.createLineBorder(new Color(0, 255, 0)));
        panelTrenPrincipal.setBackground(Color.LIGHT_GRAY);

        dropPrincipal = new PanelDropTarget(panelTrenPrincipal, this);
        dropPrincipal.setHabilitado(true);
        dropPrincipal.setConector(conector);
        dropPrincipal.setMotor(Motor);

        tablero.add(panelTrenPrincipal);
        tablero.validate();
    }

    @Override
    public void setMotor(Ficha motor) {
        Motor = motor;
    }

    @Override
    public void iniciarTurno() {
        this.turnoEnProceso = true;        
    }

    public void terminarTurno() {
        this.turnoEnProceso = false;
        conector.finTurno();
        haComido = false;
        cmdComer.setText(COMER_TEXTO_BOTON);                        
        cmdComer.setEnabled(false);        
    }

    @Override
    public void actualizaInterfaz() {
        if (!turnoEnProceso) {
            //Cuando no hay turno simplemente deshabilitamos todos los componentes.
            cmdComer.setEnabled(false);
            for (Component component : panelFichas.getComponents()) {
                component.setEnabled(false);
            }
        } else {
            //Cuando hay turno simplemente habilitamos todos los componentes.        
            cmdComer.setEnabled(true);
            for (Component component : panelFichas.getComponents()) {
                component.setEnabled(true);
            }
        }
    }
}
